module MIPSControl(
    input [31:0] inst_from_IF_ID,
    input clk, rst,
    input Detect_to_Control,               // clear signals when it is true
    
    output reg JRFlush, JFlush,            // Jump signals,work at ID
    output reg branch_beq, branch_bne,     // work at MEM
    output reg JALFlush,                   // work at WB

    output reg ALUSrc, RegDst,             // work at EX 
    output reg [2:0] ALUop,                // work at EX
    output reg MemWrite, MeMRead,          // work at MEM   
    output reg RegWrite, MeMtoReg,         // work at WB
    output reg SignSelect                  // work at EX
);
wire [5:0] Opcode;
wire [5:0] Funcode;
assign Opcode = inst_from_IF_ID[31:26];
assign Funcode = inst_from_IF_ID[5:0];

always@(*)begin
    if(Detect_to_Control==1)begin
        MemWrite <= 1'b0; 
        MeMRead <= 1'b0;
        RegWrite <= 1'b0; 
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0; 
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;      
    end else begin
    case(Opcode)
    6'b000000:begin      // R type
    // add,sub,and,or,xor,slt,sll,srl,nor,jr
        ALUop <= 3'b010;
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b1;       // address is rd
        ALUSrc <= 1'b0;       // read data2
        MemWrite <= 1'b0; 
        MeMRead <= 1'b0;
        RegWrite <= 1'b1;
        MeMtoReg <= 1'b0;
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;
        SignSelect <= 1'b0;
        if(Funcode==6'b001000)JRFlush =1'b1;  // JR enable
        else JRFlush =1'b0; 
    end
    6'b100011:begin      // lw
        ALUop <= 3'b000;
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;
        RegDst <= 1'b0;       // address is rt
        ALUSrc <= 1'b1;       // read offset
        MemWrite <= 1'b0; 
        MeMRead <= 1'b1;      // load data
        RegWrite <= 1'b1;
        MeMtoReg <= 1'b1;     // data from dcache
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b1;
    end
    6'b101011:begin      // sw
        ALUop <= 3'b000;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       // address is rt
        ALUSrc <= 1'b1;       // read offset
        MemWrite <= 1'b1;     // save data
        MeMRead <= 1'b0;
        RegWrite <= 1'b0;     // no need to write regs when sw
        MeMtoReg <= 1'b1;     // data from dcache    
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b1;
    end
    6'b001000:begin     // addi
        ALUop <= 3'b111;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       // address is rt
        ALUSrc <= 1'b1;       // read immediate
        MemWrite <= 1'b0;    
        MeMRead <= 1'b0;
        RegWrite <= 1'b1;     // write regs 
        MeMtoReg <= 1'b0;     // data from ALU    
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b1;
    end
    6'b001001:begin     //addiu
        ALUop <= 3'b000;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       // address is rt
        ALUSrc <= 1'b1;       // read immediate
        MemWrite <= 1'b0;    
        MeMRead <= 1'b0;
        RegWrite <= 1'b1;     // write regs 
        MeMtoReg <= 1'b0;     // data from ALU    
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b1;
    end
    6'b001100:begin     // andi
        ALUop <= 3'b100;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       // address is rt
        ALUSrc <= 1'b1;       // read immediate
        MemWrite <= 1'b0;    
        MeMRead <= 1'b0;
        RegWrite <= 1'b1;     // write regs 
        MeMtoReg <= 1'b0;     // data from ALU    
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b0;
    end
    6'b001101:begin      // ori
        ALUop <= 3'b011;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       // address is rt
        ALUSrc <= 1'b1;       // read immediate
        MemWrite <= 1'b0;    
        MeMRead <= 1'b0;
        RegWrite <= 1'b1;     // write regs 
        MeMtoReg <= 1'b0;     // data from ALU    
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b0;
    end
    6'b001110:begin     // xori
        ALUop <= 3'b101;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       // address is rt
        ALUSrc <= 1'b1;       // read immediate
        MemWrite <= 1'b0;    
        MeMRead <= 1'b0;
        RegWrite <= 1'b1;     // write regs 
        MeMtoReg <= 1'b0;     // data from ALU    
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b0;
    end
    6'b001111:begin     // lui
        ALUop <= 3'b110;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       // address is rt
        ALUSrc <= 1'b1;       // read immediate
        MemWrite <= 1'b0;    
        MeMRead <= 1'b0;
        RegWrite <= 1'b1;     // write regs 
        MeMtoReg <= 1'b0;     // data from ALU    
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b0;
    end
    6'b000100:begin      //beq
        ALUop <= 3'b001;        
        branch_beq <= 1'b1; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       // address is immediate
        ALUSrc <= 1'b0;       // read rt
        MemWrite <= 1'b0;    
        MeMRead <= 1'b0;
        RegWrite <= 1'b0;     // no need to write regs 
        MeMtoReg <= 1'b0;     // data from ALU    
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b1;
    end
    6'b000101:begin      // bne
        ALUop <= 3'b001;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b1;        
        RegDst <= 1'b0;       // address is immediate
        ALUSrc <= 1'b0;       // read rt
        MemWrite <= 1'b0;    
        MeMRead <= 1'b0;
        RegWrite <= 1'b0;     // no need to write regs 
        MeMtoReg <= 1'b0;     // data from ALU    
        JALFlush <= 1'b0; 
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b1;
    end
    6'b000010:begin     // J
        ALUop <= 3'b001;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       // address is immediate
        ALUSrc <= 1'b0;       // read rt
        MemWrite <= 1'b0;    
        MeMRead <= 1'b0;
        RegWrite <= 1'b0;     // no need to write regs 
        MeMtoReg <= 1'b0;     // data from ALU    
        JALFlush <= 1'b0; 
        JFlush <= 1'b1;       // J enable
        JRFlush =1'b0;
        SignSelect <= 1'b1;
    end
    6'b000011:begin     // Jal
        ALUop <= 3'b001;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       
        ALUSrc <= 1'b0;       
        MemWrite <= 1'b0;    
        MeMRead <= 1'b0;
        RegWrite <= 1'b1;     // need to write regs 
        MeMtoReg <= 1'b0;      
        JALFlush <= 1'b1;     // Jal enable
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b1;
    end
    default:begin
        ALUop <= 3'b001;        
        branch_beq <= 1'b0; 
        branch_bne <= 1'b0;        
        RegDst <= 1'b0;       
        ALUSrc <= 1'b0;       
        MemWrite <= 1'b0;     // can't write cache
        MeMRead <= 1'b0;      // can't read cache
        RegWrite <= 1'b0;     // can't write regs 
        MeMtoReg <= 1'b0;      
        JALFlush <= 1'b0;    
        JFlush <= 1'b0;    
        JRFlush =1'b0;
        SignSelect <= 1'b1;
    end
    endcase
    end
end
endmodule